PATHMac OS 8 and 9 Developer Documentation > Human Interface Toolbox > Window Manager >

Programming With the Mac OS 8.5 Window Manager


Supporting Window Proxy Icons

With Mac OS 8.5, document windows support the display of a small icon in the window's title bar, next to the window title, that serves as a proxy for the document's icon in the Finder. This proxy icon should appear and behave the way the document's icon does in the Finder.

Your application can call the function SetWindowProxyCreatorAndType when you want to establish a proxy icon for a window, but the window's data has not yet been saved to a file. By passing SetWindowProxyCreatorAndType the creator and type of the file that the window is to contain, you can provide visual consistency with other windows that have saved files and with the Finder. Listing 2-1 in Creating a Window provides an example of a simple function for creating and displaying a window that includes using SetWindowProxyCreatorAndType to establish a proxy icon.

If the window's data has been saved to a file, your application can call the functions SetWindowProxyFSSpec or SetWindowProxyAlias to associate the file with the window and thereby establish the proxy icon.

Once a window has a proxy icon, the user should be able to manipulate it as if they were performing actions with a Finder icon for the window's file. For example, if a user drags a proxy icon to a folder, Finder window, the desktop, or another volume, the file represented by the proxy icon should be moved or copied accordingly, as if the user had dragged the file's icon in the Finder.

Your application detects a proxy icon drag when the function FindWindow returns the inProxyIcon result code, and it can use Window Manager-supplied functions to handle the drag process. If the proxy icon represents an object type handled by the Window Manager (currently, files), the Window Manager can handle all aspects of the drag process itself, and your application should simply call the function TrackWindowProxyDrag . If your application calls the TrackWindowProxyDrag function it does not have to call the Drag Manager function WaitMouseMoved before starting to track the drag, as the Window Manager handles this automatically. Tracking a Window Proxy Icon Drag provides an example of how your application might call TrackWindowProxyDrag .

Because a user can so readily use a proxy icon to manipulate a document file while the document is itself open, your application should call a function in its event loop to synchronize the file data for all of its document windows. While keeping your application's file data synchronized with that of the Finder is a good practice in general, it is especially important if your application is using proxy icons in its document windows. Because a proxy icon is much more prominent to a user than a Finder icon when the user is working in an open document, it is therefore more likely that the user may move the file represented by the proxy icon while the document is open.

For example, if a user opens "My Document" in an application, then drags the proxy icon for "My Document" to a different folder, the application may still expect "My Document" to be in its original location. Additionally, the user may change the name of "My Document" to "Your Document" or place "My Document" in the Trash folder while "My Document" is open.

Optimally, your application should synchronize itself with the actual location of files on disk after every call to WaitNextEvent . This is preferable to performing file synchronization after calling TrackWindowProxyDrag , because some time may elapse between the time TrackWindowProxyDrag returns and the time that the file is actually moved on disk.

The application-defined function MySynchronizeFiles shown in Listing 2-2 is intended to be called after every call to WaitNextEvent . For each of an application's document windows, MySynchronizeFiles updates the application's internal data structures to match that of the file as it exists on disk. The MySynchronizeFiles function additionally ensures that the name of the document window is changed to match the name of the file on disk, and closes the document window if the file is moved to the Trash folder.

Listing 2-2 Synchronizing files for all document windows

static void MySynchronizeFiles( void )
{
    
    // File synchronization for all document windows
    
    static UInt32   nextSynchTicks = 0;
    UInt32          currentTicks;
    WindowPtr       currentWindow;
    OSStatus        trashStatus;
    SInt16          trashVRefNum;
    SInt32          trashDirID;
    
    currentTicks = TickCount();
    currentWindow = FrontNonFloatingWindow();
    
    // Find the Trash folder
    trashStatus = FindFolder(   kOnSystemDisk,
                                kTrashFolderType,
                                kDontCreateFolder,
                                &trashVRefNum,
                                &trashDirID );
    
    if( currentTicks > nextSynchTicks )
    {
        // Loop over all document windows,
        // searching for files whose locations have changed
        while ( currentWindow != NULL )
        {
            // Note: DocumentWindowData is a placeholder for
            // your application's document data structure
            DocumentWindowData *documentWindowData = GetWRefCon(currentWindow);
            
            // If the window is owned by this application...
            if( documentWindowData != NULL )
            {
                Boolean     aliasChanged;
                FSSpec      newSpec;
                FolderType  folder;
                
                aliasChanged = false;
                folder = 0;
                
                // Ask the Alias Manager for the document's file location...
                (void) ResolveAlias(    NULL,
                                        documentWindowData->fileAlias,
                                        &newSpec,
                                        &aliasChanged );
                if( aliasChanged )
                {
                    // The file location has changed; update the window
                    documentWindowData->fileSpec = newSpec;
                    
                    // The user might have renamed the file
                    SetWTitle( currentWindow, newSpec.name );
                    
                }
                
                // Close the document if the user moved the file into the Trash
                //
                // We need to walk up the file's parent folder hierarchy to ensure
                // that the user hasn't moved it into a folder inside the Trash
                //
                // We ignore the aliasChanged flag because the parent folder
                // hierarchy can change without affecting the alias
                
                if( trashStatus == noErr )
                {
                    do
                    {
                        // If we've reached a root folder, we know
                        // the file's not in the Trash
                        
                        if( newSpec.parID == fsRtParID )
                            break;

                        // If the Trash is a parent of the original file,
                        // close the window
                        
                        if( (newSpec.vRefNum == trashVRefNum)
                            &&  (newSpec.parID == trashDirID)
                            )
                        {
                            // Your app's "close document window" code goes here...
                            break;
                        }
                    } while( FSMakeFSSpec(  newSpec.vRefNum,
                                            newSpec.parID,
                                            "\p",
                                            &newSpec ) == noErr );
                    
                }
            }
            
            currentWindow = GetNextWindow( currentWindow );
        }
        
        // To avoid calling ResolveAlias too often, wait at least
        // 1/4 second between synchronization iterations
        nextSynchTicks = ( currentTicks + 15 );
    }
}

Applications typically track the modification state of a document in order to inform the user that they have made changes to the document which they might wish to save before closing the window. Your application should inform the Window Manager when a document has unsaved changes by calling the function SetWindowModified . When you do so, the Window Manager displays the document's proxy icon in a disabled state and prevents the user from dragging the proxy icon. Disabled proxy icons cannot be dragged because unsaved documents cannot be moved or copied in a manner predictable to the user. Setting a Window's Modification State provides an example of how your application might call SetWindowModified .

IMPORTANT

The only time that a document's proxy icon should be disabled is when the document has unsaved changes. Your application should not disable the proxy icon at any other time.

Finally, when the user drags content that your application can accept into the content area of one of its windows, the window's structure region, including the proxy icon, should become highlighted. This gives visual feedback that the window is a valid destination for the content. Applications typically call the Drag Manager functions ShowDragHilite and HideDragHilite to indicate that a window is a valid drag-and-drop destination. If your application does not do this--that is, if your application implements any type of custom drag highlighting, such as highlighting more than one area of a window at a time--it must call the function HiliteWindowFrameForDrag .


© 1999 Apple Computer, Inc. – (Last Updated 18 March 99)